#include "game_timer.h"
#include "game_macros.h"
#include "game_ev.h"
#include <event2/event.h>


const char* CGameTimerEvent::TIMER            = "timer";
const char* CGameTimerEvent::TIMER_COMPLETE   = "timer_complete";


CGameTimer::CGameTimer():_running(FALSE),_currentCount(0)
{  }

CGameTimer::~CGameTimer(){
  if(NULL != _event){
    event_del(_event);
    event_free(_event);
    _event = NULL;
  }
}

BOOL CGameTimer::init(){
  CC_ASSERT(false,"CGameTimer","Must init on CGameTimer::init(UINT32 delay, UINT32 repeat).");
}

template <typename TYPE, void (TYPE::*onTick)() >  
void CGameTimer::__timer_cb(int sock, short which, void *arg){
  TYPE* This = (TYPE*)arg;     
  This->onTick();    
}

void CGameTimer::onTick(){
  CC_DEBUG("CGameTimer","%s","tick");
  if(NULL != _event){
    event_free(_event);
    _event = NULL;
  }

  if(!_running)
    return;
 
  if(0 == _repeat || _currentCount < _repeat){
    dispatch(new CGameTimerEvent(CGameTimerEvent::TIMER,static_cast<CGameRef*>(this)));
    tick();
  }else{
    dispatch(new CGameTimerEvent(CGameTimerEvent::TIMER_COMPLETE,static_cast<CGameRef*>(this)));
  }

  
}

void CGameTimer::tick(){
  CGame::Event::EventContext_t* ctx = new CGame::Event::EventContext_t();
  ctx->_this = this;
  _event = event_new(_evbase,-1,0,CGameTimer::__timer_cb<CGameTimer,&CGameTimer::onTick>,this);

  timeval tv = {.tv_sec = 0,.tv_usec = (int)_delay * 1000};

  event_add(_event,&tv);
  _currentCount++;
  // even
}

BOOL CGameTimer::init(event_base* evbase,mseconds_t delay, UINT32 repeat){
  do{
    CC_BREAK_IF(!CGameEventDispatcher::init(evbase));

    _delay = delay;
    _repeat = repeat;

    _running = TRUE;


    
    tick();
    return TRUE;
  }while(true);

  return FALSE;
}

BOOL CGameTimer::init(mseconds_t delay, UINT32 repeat){
  return init(g_CGameEV.getBase(),delay,repeat);
}

void CGameTimer::reset(){
  _currentCount = 0;
}


void CGameTimer::stop(){
  _running = false;
  if(NULL != _event){
    event_del(_event);
    event_free(_event);
    _event = NULL;
  }
}
